using System;
using System.Collections.Generic;
using System.IO;
using System.Web.Mvc;
using Orchard.Conditions.Services;
using Orchard.ContentManagement;
using Orchard.DisplayManagement;
using Orchard.Environment;
using Orchard.Localization;
using Orchard.Projections.Models;
using Orchard.Tokens;
using Orchard.Utility.Extensions;

namespace Orchard.Projections.Services
{
    public class PropertyShapes : IDependency
    {
        private readonly Work<ITokenizer> _tokenizerWork;
        private readonly Work<IConditionManager> _conditionManagerWork;
        private readonly Dictionary<string, bool> _evaluations = new Dictionary<string, bool>();

        public PropertyShapes(Work<ITokenizer> tokenizerWork, Work<IConditionManager> conditionManagerWork)
        {
            _tokenizerWork = tokenizerWork;
            _conditionManagerWork = conditionManagerWork;
            T = NullLocalizer.Instance;
        }

        public Localizer T { get; set; }

        [Shape]
        public void Properties(dynamic Display, TextWriter Output, HtmlHelper Html, IEnumerable<dynamic> Items)
        {
            foreach (var item in Items)
            {
                if ((bool)item.Property.ExcludeFromDisplay)
                {
                    continue;
                }

                Output.WriteLine(Display(item));
            }
        }

        [Shape]
        public void LayoutGroup(dynamic Display, TextWriter Output, HtmlHelper Html, dynamic Key, dynamic List)
        {
            Output.WriteLine(Display(Key));
            Output.WriteLine(Display(List));
        }

        [Shape]
        public void PropertyWrapper(
            dynamic Display,
            TextWriter Output,
            HtmlHelper Html,
            UrlHelper Url,
            dynamic Item,
            ContentItem ContentItem,
            ContentItemMetadata ContentItemMetadata,
            PropertyRecord Property)
        {
            // Display will encode any string which is not IHtmlString.
            string resultOutput = Convert.ToString(Display(Item));

            var tokenData = new Dictionary<string, object> { { "Text", resultOutput }, { "Content", ContentItem } };

            if (!string.IsNullOrWhiteSpace(Property.RewriteOutputCondition) &&
                _conditionManagerWork.Value.Matches(_tokenizerWork.Value.Replace(Property.RewriteOutputCondition, tokenData)))
                resultOutput = string.IsNullOrWhiteSpace(Property.RewriteText) ? "" : _tokenizerWork.Value.Replace(Property.RewriteText, tokenData);

            var resultIsEmpty = string.IsNullOrEmpty(resultOutput) || (resultOutput == "0" && Property.ZeroIsEmpty);

            if (Property.HideEmpty && resultIsEmpty)
            {
                return;
            }

            if (Property.StripHtmlTags)
            {
                resultOutput = resultOutput.RemoveTags();
            }

            if (Property.TrimLength)
            {
                var ellipsis = Property.AddEllipsis ? "&#160;&#8230;" : "";
                resultOutput = resultOutput.Ellipsize(Property.MaxLength, ellipsis, Property.TrimOnWordBoundary);
            }

            if (Property.TrimWhiteSpace)
            {
                resultOutput = resultOutput.Trim();
            }

            if (Property.PreserveLines)
            {
                using (var sw = new StringWriter())
                {
                    using (var sr = new StringReader(resultOutput))
                    {
                        string line;
                        while (null != (line = sr.ReadLine()))
                        {
                            sw.WriteLine(line);
                            sw.WriteLine("<br />");
                        }
                    }
                    resultOutput = sw.ToString();
                }
            }

            var wrapperTag = new TagBuilder(Property.CustomizeWrapperHtml && !string.IsNullOrEmpty(Property.CustomWrapperTag) ? Property.CustomWrapperTag : "div");

            if (Property.CustomizeWrapperHtml && !string.IsNullOrEmpty(Property.CustomWrapperCss))
            {
                wrapperTag.AddCssClass(_tokenizerWork.Value.Replace(Property.CustomWrapperCss, new Dictionary<string, object>()));
            }

            if (!(Property.CustomizeWrapperHtml && Property.CustomWrapperTag == "-"))
            {
                Output.Write(wrapperTag.ToString(TagRenderMode.StartTag));
            }

            if (Property.CreateLabel)
            {
                var labelTag = new TagBuilder(Property.CustomizeLabelHtml && !string.IsNullOrEmpty(Property.CustomLabelTag) ? Property.CustomLabelTag : "span");

                if (Property.CustomizeLabelHtml && !string.IsNullOrEmpty(Property.CustomLabelCss))
                {
                    labelTag.AddCssClass(_tokenizerWork.Value.Replace(Property.CustomLabelCss, new Dictionary<string, object>()));
                }

                if (!(Property.CustomizeLabelHtml && Property.CustomLabelTag == "-"))
                {
                    Output.Write(labelTag.ToString(TagRenderMode.StartTag));
                }

                Output.Write(_tokenizerWork.Value.Replace(Property.Label, new Dictionary<string, object>()));

                if (!(Property.CustomizeLabelHtml && Property.CustomLabelTag == "-"))
                {
                    Output.Write(labelTag.ToString(TagRenderMode.EndTag));
                }
            }

            var propertyTag = new TagBuilder(Property.CustomizePropertyHtml && !string.IsNullOrEmpty(Property.CustomPropertyTag) ? Property.CustomPropertyTag : "span");

            if (Property.CustomizePropertyHtml && !string.IsNullOrEmpty(Property.CustomPropertyCss))
            {
                propertyTag.AddCssClass(_tokenizerWork.Value.Replace(Property.CustomPropertyCss, new Dictionary<string, object>()));
            }

            if (!(Property.CustomizePropertyHtml && Property.CustomPropertyTag == "-"))
            {
                Output.Write(propertyTag.ToString(TagRenderMode.StartTag));
            }

            if (!resultIsEmpty)
            {
                if (Property.LinkToContent)
                {
                    var linkTag = new TagBuilder("a");
                    linkTag.Attributes.Add("href", Url.RouteUrl(ContentItemMetadata.DisplayRouteValues));
                    linkTag.InnerHtml = resultOutput;
                    Output.Write(linkTag.ToString());
                }
                else
                {
                    Output.Write(resultOutput);
                }
            }
            else
            {
                Output.Write(_tokenizerWork.Value.Replace(Property.NoResultText, new Dictionary<string, object>()));
            }

            if (!(Property.CustomizePropertyHtml && Property.CustomPropertyTag == "-"))
            {
                Output.Write(propertyTag.ToString(TagRenderMode.EndTag));
            }

            if (!(Property.CustomizeWrapperHtml && Property.CustomWrapperTag == "-"))
            {
                Output.Write(wrapperTag.ToString(TagRenderMode.EndTag));
            }
        }
    }
}
